

class LookupTable:
	""" creates dictionary to quickly read stored values
		read values from offseted input are interpolated
	"""
	def __init__(self, mapped_indexes):
		""" mapped_indexes dictionary should have ints as key values
		"""
		if not isinstance(mapped_indexes, dict): raise Exception('first param must be dictionary')
		self._table = mapped_indexes.copy()
		#self._unit = value_unit
		indexes = self._table.keys()
		indexes.sort()
		self._min = indexes[0]
		self._max = indexes[-1]
		self._min_result = mapped_indexes[self._min]
		self._max_result = mapped_indexes[self._max]
		self._unit = self._greatest_common_divisor(indexes)
		self._unit_half = self._unit / 2.0
		
		## fill in missing records
		index, last_value = self._min, self._table[self._min]
		missing_indexes = []
		while index <= self._max:
			if index not in self._table:
				missing_indexes.append( index )
			else:
				current_value = self._table[index]
				if len(missing_indexes) > 0:
					increment = (current_value - last_value) / (len(missing_indexes)+1)
					value = last_value
					for new_index in missing_indexes:
						value += increment
						self._set_item_(new_index, value)
					missing_indexes = []
				
				last_value = current_value
			
			index += self._unit
	
	def _set_item_(self, input, value):
		""" map index to int value in dict then store it
		"""
		index = int(input / self._unit)
		unit_part = input % self._unit
		if unit_part > self._unit_half: index += 1
		self._table[index] = value
	
	def __getitem__(self, input):
		""" returns stored result
		"""
		## for values outside of our table :
		if input < self._min: return self._min_result
		elif input > self._max: return self._max_result
		
		## calculate index
		index = int(input / self._unit)
		unit_part = abs(input) % self._unit
		if unit_part > self._unit_half:
			if input >= 0.0: index += 1
			else: index -= 1
		return self._table[index]

	def _gcd(self, a, b):
	    """Return greatest common divisor using Euclid's Algorithm."""
	    while b:      
	        a, b = b, a % b
	    return a
	
	def _lcm(self, a, b):
	    """Return lowest common multiple."""
	    return a * b // self._gcd(a, b)
	
	def _greatest_common_divisor(self, array):
		""" returns gdc of list """
		return reduce(self._gcd, array)
	
	def _lowest_common_multiple(self, array):
	    """Return lcm of array."""   
	    return reduce(self._lcm, array)
	
	


if __name__ == '__main__':
	print 'local test: '
	
	table = LookupTable(
		{
			-10.0	: -100,
			-5.0	: -30,
			-2.0	: -7,
			-1.0	: -0.5,
			0.0 	: 0,
			1.0 	: 0.5,
			2.0 	: 7,
			5.0 	: 30,
			10.0	: 100,
		} )
	
	index = -12
	while index < 12:
		print table[index]
		index += 0.5
	
	print 'done.'







